package com.jyw.business.obstacles.service.impl;

import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

import cn.hutool.core.date.DateUtil;
import com.jyw.business.obstacles.constant.TalkTypeConstant;
import com.jyw.business.obstacles.domain.ObsLocalPhone;
import com.jyw.business.obstacles.domain.ObsOrderInfo;
import com.jyw.business.obstacles.domain.dto.web.RepairUserDto;
import com.jyw.business.obstacles.domain.vo.web.OrderInfoWebVO;
import com.jyw.business.obstacles.domain.vo.web.ServerDeskWebSocketVO;
import com.jyw.business.obstacles.service.IObsLocalPhoneService;
import com.jyw.business.obstacles.service.IObsOrderInfoService;
import com.jyw.business.obstacles.utils.WebSocketUtils;
import com.jyw.common.constant.CacheConstants;
import com.jyw.common.core.domain.entity.SysDept;
import com.jyw.common.core.domain.entity.SysUser;
import com.jyw.common.core.redis.RedisCache;
import com.jyw.system.domain.SysUserDept;
import com.jyw.system.service.ISysDeptService;
import com.jyw.system.service.ISysUserDeptService;
import com.jyw.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.jyw.business.obstacles.mapper.ObsPhoneBoxMapper;
import com.jyw.business.obstacles.domain.ObsPhoneBox;
import com.jyw.business.obstacles.service.IObsPhoneBoxService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * 报障-电话盒子Service业务层处理
 * 
 * @author system
 * @date 2023-08-22
 */
@Service
@Slf4j
public class ObsPhoneBoxServiceImpl extends ServiceImpl<ObsPhoneBoxMapper,ObsPhoneBox> implements IObsPhoneBoxService
{
    @Resource
    private ObsPhoneBoxMapper obsPhoneBoxMapper;

    @Resource
    private IObsOrderInfoService orderInfoService;

    @Resource
    private IObsLocalPhoneService localPhoneService;

    @Resource
    private ISysDeptService deptService;

    @Resource
    private ISysUserDeptService userDeptService;

    @Resource
    private ISysUserService userService;

    @Resource
    private RedisCache redisCache;

    /**
     * 查询报障-电话盒子
     * 
     * @param id 报障-电话盒子主键
     * @return 报障-电话盒子
     */
    @Override
    public ObsPhoneBox selectObsPhoneBoxById(Long id)
    {
        return obsPhoneBoxMapper.selectObsPhoneBoxById(id);
    }

    /**
     * 查询报障-电话盒子列表
     * 
     * @param obsPhoneBox 报障-电话盒子
     * @return 报障-电话盒子
     */
    @Override
    public List<ObsPhoneBox> selectObsPhoneBoxList(ObsPhoneBox obsPhoneBox)
    {
        return obsPhoneBoxMapper.selectObsPhoneBoxList(obsPhoneBox);
    }

    /**
     * 新增报障-电话盒子
     * 
     * @param obsPhoneBox 报障-电话盒子
     * @return 结果
     */
    @Override
    public int insertObsPhoneBox(ObsPhoneBox obsPhoneBox)
    {
        return obsPhoneBoxMapper.insertObsPhoneBox(obsPhoneBox);
    }

    /**
     * 修改报障-电话盒子
     * 
     * @param obsPhoneBox 报障-电话盒子
     * @return 结果
     */
    @Override
    public int updateObsPhoneBox(ObsPhoneBox obsPhoneBox)
    {
        return obsPhoneBoxMapper.updateObsPhoneBox(obsPhoneBox);
    }

    /**
     * 批量删除报障-电话盒子
     * 
     * @param ids 需要删除的报障-电话盒子主键
     * @return 结果
     */
    @Override
    public int deleteObsPhoneBoxByIds(Long[] ids)
    {
        return obsPhoneBoxMapper.deleteObsPhoneBoxByIds(ids);
    }

    /**
     * 删除报障-电话盒子信息
     * 
     * @param id 报障-电话盒子主键
     * @return 结果
     */
    @Override
    public int deleteObsPhoneBoxById(Long id)
    {
        return obsPhoneBoxMapper.deleteObsPhoneBoxById(id);
    }

    @Override
    public void saveVaaFile(MultipartFile files, String url) {
        String name = files.getOriginalFilename();
        ObsPhoneBox phoneBox = getOne(lambdaQuery().eq(ObsPhoneBox::getCallAccept,name));
        if(ObjectUtils.isEmpty(phoneBox)){
            return;
        }
        // 判断是否已经创建电话记录
        ObsOrderInfo oldInfo = orderInfoService.getInfoByOrderNum(phoneBox.getOrderNum());
        // 下载文件到服务器
        if (StringUtils.isEmpty(oldInfo.getRecording())) {
            //创建文件
            oldInfo.setRecording(url);
            timeAndPhone(oldInfo, phoneBox);
            oldInfo.setOrderNum(phoneBox.getOrderNum());
            orderInfoService.saveOrUpdate(oldInfo);
        }
    }

    /**
     * 开始话务(弹屏)
     * @param phone 来电电话
     * @param callAccept 流水号
     * @param workPhone 服务台号码（座席号码）
     * @param startTime 来电时间
     */
    @Override
    public void startWork(String phone, String callAccept, String workPhone, Date startTime) {
        RepairUserDto userDto = getRepairUser(phone);

        Long userId = redisCache.getCacheMapValue(CacheConstants.SEAT_NOW,workPhone);

        ObsPhoneBox box = getByOtheraccept(callAccept);
        ObsOrderInfo orderInfo = null;
        if(box == null) {
            // 创建info(state = 0 为自动录入)
            orderInfo = ObsOrderInfo.builder().phone(phone).deptId(userDto.getDeptId())
                    .place(userDto.getDeptPlace())
                    .user(userDto.getUserName())
                    .callType(TalkTypeConstant.MISSED_CALL)
                    .build();
            log.info("------来电生成order info" + orderInfo.toString());
            if (userId != null) {
                orderInfo.setReception(userId);
            }
            orderInfoService.save(orderInfo);


            // 创建三方表信息
            box = ObsPhoneBox.builder().status("0")
                    .otheraccept(callAccept)
                    .callerIdNumber(phone)
                    .destinationNumber(workPhone)
                    .orderNum(orderInfo.getOrderNum())
                    .createdTime(new Date())
                    .build();
            if(startTime != null) {
                box.setCreatedTime(startTime);
            }
            save(box);
        }else {
            orderInfo = orderInfoService.getInfoByOrderNum(box.getOrderNum());
            if (userId != null) {
                orderInfo.setReception(userId);
                orderInfoService.updateById(orderInfo);
            }
        }

        log.info("------接听生成box" + box.toString());

        log.info("[busOrderListener][createInfoByPhoneBox] externalStartEvent user id:{}",userId);

        //推送前端来电信息
        if (!ObjectUtils.isEmpty(userId)) {
            OrderInfoWebVO busOrderInfoWebDto = new OrderInfoWebVO();
            BeanUtils.copyProperties(orderInfo, busOrderInfoWebDto);
            busOrderInfoWebDto.setUpdateTime(DateUtil.format(orderInfo.getUpdateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            busOrderInfoWebDto.setCreateTime(DateUtil.format(orderInfo.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            try {
                WebSocketUtils.send(ServerDeskWebSocketVO.ofFaultInfo(busOrderInfoWebDto), userId);
            } catch (Exception e) {
                log.error("推送来电消息给PC失败",e);
            }
        }else {
            log.error("线程:{},推送来电消息给PC失败,未查询到电话:{} 对应的坐席人员!",Thread.currentThread().getName(),workPhone);
        }
    }

    @Override
    public ObsPhoneBox getByOtheraccept(String otherAccept) {
        return getOne(lambdaQuery().eq(ObsPhoneBox::getOtheraccept,otherAccept));
    }




    private void timeAndPhone(ObsOrderInfo orderInfo, ObsPhoneBox phoneBox) {
        // 通话时间计算
        if("0".equals(phoneBox.getStatus())) {
            log.info("设置工单为未接：{}",orderInfo.getOrderNum());
            orderInfo.setCallType(TalkTypeConstant.MISSED_CALL);
        }else if("1".equals(phoneBox.getStatus())) {
            log.info("设置工单为已接：{}",orderInfo.getOrderNum());
            orderInfo.setCallType(TalkTypeConstant.PICKED_UP);//已接
        }
        // 主叫号码
        String callerIdNumber = phoneBox.getCallerIdNumber();
        // 被叫号码
        String destinationNumber = phoneBox.getDestinationNumber();
        // 获取所有本地座机电话
        List<ObsLocalPhone> localPhoneList = localPhoneService.list();
        if (localPhoneList.stream().filter(local -> local.getPhoneNum().equals(callerIdNumber)).count() == 1) {
            // 主叫是服务台
            if (orderInfo.getPhone() == null) {
                orderInfo.setPhone(destinationNumber);
            }
            setParma(orderInfo, destinationNumber,callerIdNumber);
        } else {
            // 被叫是服务台
            if (orderInfo.getPhone() == null) {
                orderInfo.setPhone(callerIdNumber);
            }
            setParma(orderInfo, callerIdNumber,callerIdNumber);
        }
    }


    /**
     * 设置参数
     * @param orderInfo 工单信息
     * @param repairPhone 报修电话
     * @param receptionPhone 服务台电话
     */
    private void setParma(ObsOrderInfo orderInfo, String repairPhone,String receptionPhone) {
        //根据报修电话查询用户
        RepairUserDto repairUser = getRepairUser(repairPhone);
        if(!ObjectUtils.isEmpty(repairUser)){
            if (orderInfo.getUser() == null) {
                orderInfo.setUser(repairUser.getUserName());
            }
            if (orderInfo.getPlace() == null) {
                orderInfo.setPlace(repairUser.getDeptPlace());
            }
            if (orderInfo.getDeptId() == null) {
                orderInfo.setDeptId(repairUser.getDeptId());
            }

        }
        //查询服务台人员
        SysUser serverUser = userService.getOne(userService.lambdaQuery().eq(SysUser::getPhonenumber, receptionPhone));
        if(!ObjectUtils.isEmpty(serverUser)){
            orderInfo.setReception(serverUser.getUserId());
        }
    }

    /**
     * 获取报修人员信息
     * @param repairPhone
     * @return
     */
    private RepairUserDto getRepairUser(String repairPhone){
        RepairUserDto userDto = new RepairUserDto();
        SysUser repairUser = userService.getOne(userService.lambdaQuery().eq(SysUser::getPhonenumber, repairPhone));
        if(!ObjectUtils.isEmpty(repairUser)){
            userDto.setUserName(repairUser.getNickName());
            //查询用户默认部门
            List<SysUserDept> list = userDeptService.list(userDeptService.lambdaQuery().eq(SysUserDept::getUserId, repairUser.getUserId()));
            if(list.size()>0){
                SysUserDept sysUserDept = list.get(0);
                //查询用户部门信息
                SysDept dept = deptService.getById(sysUserDept.getDeptId());
                if(!ObjectUtils.isEmpty(dept)){
                    userDto.setDeptPlace(dept.getDeptPlace());
                    userDto.setDeptId(dept.getDeptId());
                }
            }

        }
        return userDto;
    }
}
